package ast


/*
exp ::=  nil | false | true | Numeral | LiteralString | ‘...’ | functiondef |
	 prefixexp | tableconstructor | exp binop exp | unop exp

prefixexp ::= var | functioncall | ‘(’ exp ‘)’

var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name

functioncall ::=  prefixexp args | prefixexp ‘:’ Name args
*/


// 空接口interface{}没有任何方法签名，也就意味着任何类型都实现了空接口
// 其作用类似面向对象语言中的根对象object
type Stat interface{}


// 空语句没有任何语义，仅起分隔作用
// 所以EmptyStat结构体也没有任何字段
type EmptyStat struct {}		// ";"


// break语句在代码生成阶段产生一条跳转指令
// 所以我们需要记录其行号
type BreakStat struct {			// "break"
	Line	int 	
}


// 标签和goto语句搭配使用，用来实现任意跳转
// 所以我们需要记录标签名
type LabelStat struct {			// "::" Name "::"
	Name	string
}

type GotoStat struct {
	Name 	string				// goto Name
}


// do语句仅仅是为了给语句块引入新的作用域
// 所以DoState结构体也只有一个Block字段
type DoStat struct {			// do block end
	Block	*Block
}


// 函数调用既可以是语句，也可以是表达式
// 所以我们仅仅是起了一个别名
type FuncCallStat =	FuncCallExp		// functioncall


// while exp do block end
type WhileStat struct {
	Exp 	Exp
	Block 	*Block
}


// repeat block until exp
type RepeatStat struct {
	Block 	*Block
	Exp 	Exp
}


// 表达式收集到Exps字段里
// 把语句块收集到Blocks字段里
// 表达式和语句块按照索引一一对应
// 索引0处世if-then表达式和块
// 其余索引处是elseif-then表达式和块
// if exp then block {elseif exp then block} [else block] end
type IfStat struct {
	Exps	[]Exp
	Blocks	[]*Block
}


// for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end
type ForNumStat struct {
	LineOfFor		int
	LineOfDo 		int
	VarName			string
	InitExp			Exp
	LimitExp		Exp
	StepExp			Exp
	Block 			*Block
}


// for namelist in explist do block end
// namelist ::= Name {‘,’ Name}
// explist ::= exp {‘,’ exp}
type ForInStat struct {
	LineOfDo		int
	NameList 		[]string
	ExpList 		[]Exp
	Block 			*Block
}


// 由于Lua支持多重赋值，所以声明和赋值语句比较复杂
// 其中局部变量声明语句用于声明(并初始化)新的局部变量
// 局部变量的声明语句以关键字local开始
// 后跟逗号分隔的标识符列表
// 接着是可选的等号和逗号分隔的表达式列表
// local namelist [‘=’ explist]
// namelist ::= Name {‘,’ Name}
// explist ::= exp {‘,’ exp}
type LocalVarDeclStat struct {
	LastLine		int 
	NameList 		[]string
	ExpList 		[]Exp
}


// 赋值语句用于给变量(包括已经声明的局部变量、Upvalue或者全局变量)
// 赋值、根据键给表赋值或者修改记录的字段
// varlist ‘=’ explist
// varlist ::= var {‘,’ var}
// var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name
type AssignStat struct {
	LastLine		int
	VarList 		[]Exp
	ExpList 		[]Exp
}


// local function Name funcbody
type LocalFuncDefStat struct {
	Name 		string 				// 函数名
	Exp 		*FuncDefExp			// 函数定义表达式
}